package util.stomp;

import android.content.Context;

import com.google.gson.Gson;

import org.greenrobot.eventbus.EventBus;

import coom.MyType;
import event.CloseActEvent;
import io.reactivex.CompletableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import ui.model.MessageBean;
import ui.model.MessageDao;
import ui.model.SendModel;
import util.Base64Object;
import util.LogUtils;
import util.StringUtils;
import util.ToastUtils;
import util.sqlite.DBManager;

public class StompClientUtil {

    public static StompClient mStompClient;
    public static CompositeDisposable compositeDisposable;
    public static DBManager manager;


    /**
     * 获取数据库
     *
     * @param mContext
     * @return
     */
    public static DBManager ConnectDB(Context mContext) {
        if (manager == null) {
            manager = new DBManager(mContext);
        }
        return manager;
    }

    public static void CloseDb() {
        if (manager != null) {
            manager.closeDB();
        }
    }


    /**
     * 开启websocket
     *
     * @param connectUrl
     * @param REGISTER_URL
     */
    public static void ConnectStomp(Context mContext, String userId, String connectUrl, String REGISTER_URL) {
        mStompClient = Stomp.over(Stomp.ConnectionProvider.OKHTTP, connectUrl);
        mStompClient.withClientHeartbeat(1000).withServerHeartbeat(1000);
        ResetSubscriptions();
        Disposable dispLifecycle = mStompClient.lifecycle()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(lifecycleEvent -> {
                    switch (lifecycleEvent.getType()) {
                        case OPENED:
                            LogUtils.d("Stomp connection opened");
                            break;
                        case ERROR:
                            LogUtils.d("Stomp connection error");
                            break;
                        case CLOSED:
                            LogUtils.d("Stomp connection closed");
                            break;
                        case FAILED_SERVER_HEARTBEAT:
                            LogUtils.d("Stomp failed server heartbeat");
                            break;
                    }
                });
        compositeDisposable.add(dispLifecycle);
        Disposable dispTopic = mStompClient.topic(REGISTER_URL)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(topicMessage -> {
                    try {
                        if (!StringUtils.isEmpty(topicMessage.getPayload())) {
                            MessageDao messageDao = new Gson().fromJson(topicMessage.getPayload(), MessageDao.class);
                            if (messageDao != null) {
                                if (!StringUtils.isEmpty(messageDao.getSign())) {
                                    MessageBean messageBean = new MessageBean();
                                    messageBean.setContentInfo(messageDao.getContent());
                                    messageBean.setFromInfo(messageDao.getFrom());
                                    messageBean.setMessageType(0);
                                    messageBean.setToInfo(messageDao.getTo());
                                    messageBean.setSignInfo(messageDao.getSign());
                                    messageBean.setTimeInfo(System.currentTimeMillis());
                                    messageBean.setType("0");
                                    messageBean.setUserId(userId);
                                    ConnectDB(mContext).add(messageBean);
                                    EventBus.getDefault().post(new CloseActEvent(MyType.ReceiveMessage, messageDao.getSign()));
                                }
                            }
                        }
                    } catch (Exception e) {

                    }
                    LogUtils.d("Received " + topicMessage.getPayload());
                }, throwable -> {
                    LogUtils.d("Error on subscribe topic");
                });
        compositeDisposable.add(dispTopic);
        mStompClient.connect();
    }


    /**
     * 发送消息
     */
    public static void SendInfo(String sendUrl, String userId, String info, String name, String phone) {
        if (util.StringUtils.isEmpty(info)) {
            ToastUtils.shortToast("请填写信息");
            return;
        }
        if (mStompClient == null || !mStompClient.isConnected()) {
            return;
        }
        String signInfo = phone + "-" + System.currentTimeMillis();
        LogUtils.d("----->" + signInfo);
        LogUtils.d("----->" + name + phone);
        SendModel sendModel = new SendModel();
        sendModel.setSign(signInfo);
        sendModel.setContent(Base64Object.stringToBase64(info));//题号
        sendModel.setFrom(Base64Object.stringToBase64(name +"-"+ phone));
        String data = new Gson().toJson(sendModel);
        LogUtils.d(sendUrl);
        LogUtils.d(data);
        compositeDisposable.add(mStompClient.send(sendUrl, data)
                .compose(ApplySchedulers())
                .subscribe(() -> {
                    ToastUtils.shortToast("发送消息成功");
                    try {
                        LogUtils.d("发送消息成功");
                        MessageBean messageBean = new MessageBean();
                        messageBean.setContentInfo(info);
                        messageBean.setFromInfo(phone);
                        messageBean.setMessageType(1);
                        messageBean.setToInfo("service");
                        messageBean.setSignInfo(signInfo);
                        messageBean.setTimeInfo(System.currentTimeMillis());
                        messageBean.setType("1");
                        messageBean.setUserId(userId);
                        manager.add(messageBean);
                        EventBus.getDefault().post(new CloseActEvent(MyType.SendMessage, ""));
                    } catch (Exception e) {
                        LogUtils.d("出错");
                    }
                }, throwable -> {
                    ToastUtils.shortToast("发送消息失败");
                }));

    }

    private static void ResetSubscriptions() {
        if (compositeDisposable != null) {
            compositeDisposable.dispose();
        }
        compositeDisposable = new CompositeDisposable();
    }

    public static boolean IsOpen() {
        return mStompClient != null && mStompClient.isConnected();
    }


    public static void DestoryWebsocket() {
        if (mStompClient != null) {
            mStompClient.disconnect();
        }
        if (compositeDisposable != null) {
            compositeDisposable.dispose();
        }
    }


    private static CompletableTransformer ApplySchedulers() {
        return upstream -> upstream
                .unsubscribeOn(Schedulers.newThread())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

}
